home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #2 / Amiga Plus CD - 2004 - No. 02.iso / AmiSoft / Disk / moni / FileX-src.lha / FileX-src / undo.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-08-29  |  16.2 KB  |  518 lines

  1. #include "FileXStructs.h"
  2. #include "FileXStrings.h"
  3. #include "allprotos.h"
  4.  
  5. WORD UndoLevel = DEFAULT_UNDO_LEVEL;
  6. WORD maxundomemsize = DEFAULT_UNDO_MEM;         /* In KB */
  7.  
  8. BOOL AllocUndostructs( struct FileData *FD )
  9. {
  10.         if( FD->Undos = AllocMem( sizeof( struct Undostruct ) * UndoLevel, MEMF_CLEAR ))
  11.         {
  12.                 FD->UndoStart = 0;
  13.                 FD->UndoTiefe = 0;
  14.                 FD->Changes = FD->RedoChanges = FD->FullChanges = 0;
  15.  
  16. /*kprintf("AllocUndostructs: UndoMem:%ld\n", FD->UndoMemSize );*/
  17.  
  18.                 return( TRUE );
  19.         }
  20.         else
  21.         {
  22.                 MyRequest( MSG_INFO_GLOBAL_CANTALLOCMEM, sizeof( struct Undostruct ) * UndoLevel );
  23.                 return( FALSE );
  24.         }
  25. }
  26.  
  27. void FreeUndostructs( struct FileData *FD )
  28. {
  29.         if( FD->Undos )
  30.         {
  31.                 int k;
  32.  
  33.                 k = FD->UndoStart;
  34.  
  35.                 while( FD->Undos[ k ].typ )
  36.                 {
  37.                         if( FD->Undos[ k ].typ & ( UT_INSERT | UT_PASTE | UT_CUT ))
  38.                         {
  39.                                 FreeSpeicher( &FD->Undos[ k ].r, FD );
  40.                                 FreeSpeicher( &FD->Undos[ k ].u, FD );
  41.                         }
  42.         
  43.                         FD->UndoStart++;
  44.                 
  45.                         k++;
  46.                         if( k == UndoLevel ) k -= UndoLevel;
  47.                 }
  48.  
  49.                 FreeMem( FD->Undos, sizeof( struct Undostruct ) * UndoLevel );
  50.                 FD->Undos = 0;
  51.         }
  52.  
  53. /*if( FD->UndoMemSize )*/
  54. /*kprintf("FreeUndostructs: UndoMem:%ld\n", FD->UndoMemSize );*/
  55.  
  56.                 /* Sicherheitshalber alle Variablen zurücksetzten */
  57.  
  58.         FD->UndoMemSize = 0;
  59.         FD->UndoStart = 0;
  60.         FD->UndoTiefe = 0;
  61.         FD->Changes = FD->RedoChanges = FD->FullChanges = 0;
  62. }
  63.  
  64. /*genealogist*/
  65.  
  66. BOOL Undo( struct FileData *FD )
  67. {
  68.         struct Undostruct *u;
  69.         struct DisplayData *DD = 0;
  70.  
  71. /*      kprintf("Undo: Changes: %ld RChanges: %ld FChanges: %ld\n", FD->Changes, FD->RedoChanges, FD->FullChanges );*/
  72.  
  73.         if( AktuDD->FD == FD )
  74.                 DD = AktuDD;
  75.  
  76.         if( FD->UndoTiefe == FD->UndoStart )
  77.                 return( FALSE );
  78.  
  79.         FD->UndoTiefe--;
  80.  
  81.         if( FD->UndoTiefe < 0 ) FD->UndoTiefe += UndoLevel;
  82.  
  83.         if( FD->Changes != 0 ) FD->Changes--;
  84.         else FD->RedoChanges++;
  85.  
  86.         u = &FD->Undos[FD->UndoTiefe];
  87.  
  88.         switch( u->typ )
  89.         {
  90.                 case    UT_ASCII:
  91.                         if( DD ) SetCursor( u->pos, DD);
  92.                         FD->Mem[u->pos]=u->wert;
  93.                         AllDisplayChar( FD, FD->Undos[ FD->UndoTiefe ].pos );
  94.                         UpdateAllStatusZeilen( FD );
  95.                         break;
  96.                 case    UT_HEX_L:
  97.                         if( DD )
  98.                         {
  99.                                 SetCursor( u->pos, DD);
  100.                                 DD->Flags |= DD_HEXEDITPOS;
  101.                         }
  102.                         FD->Mem[u->pos]=u->wert;
  103.                         AllDisplayChar( FD, FD->Undos[ FD->UndoTiefe ].pos );
  104.                         UpdateAllStatusZeilen( FD );
  105.                         break;
  106.                 case    UT_HEX_H:
  107.                         if( DD )
  108.                         {
  109.                                 SetCursor(u->pos, DD);
  110.                                 DD->Flags &= ~DD_HEXEDITPOS;
  111.                         }
  112.                         FD->Mem[u->pos]=u->wert;
  113.                         AllDisplayChar( FD, FD->Undos[ FD->UndoTiefe ].pos );
  114.                         UpdateAllStatusZeilen( FD );
  115.                         break;
  116.                 case    UT_INSERT:
  117.                         if( DD ) SetCursor(u->pos, DD);
  118.                         CutBlockForce(u->pos,u->pos+u->r.len-1, (struct DisplayData *)(((UBYTE *)FD->DisplayList.lh_Head)-sizeof(struct Node)));
  119.                         break;
  120.                 case    UT_CUT:
  121.                         InsertBlockForce(u->pos,u->u.mem, u->u.len, (struct DisplayData *)(((UBYTE *)FD->DisplayList.lh_Head)-sizeof(struct Node)) );
  122.                         if( DD ) SetCursor(u->pos, DD);
  123.                         break;
  124.                 case    UT_PASTE:
  125.                         memcpy(FD->Mem+u->pos,u->u.mem,u->u.len);
  126.                         AllDisplay( FD, SCROLLERNEU );
  127.                         UpdateAllStatusZeilen( FD );
  128.                         if( DD ) SetCursor(u->pos, DD);
  129.                         break;
  130.         }
  131.  
  132.         return( TRUE );
  133. }
  134.  
  135. BOOL Redo( struct FileData *FD )
  136. {
  137.         struct Undostruct *u;
  138.         struct DisplayData *DD = 0;
  139.  
  140. /*      kprintf("Redo: Changes: %ld RChanges: %ld FChanges: %ld\n", FD->Changes, FD->RedoChanges, FD->FullChanges );*/
  141.  
  142.         if( AktuDD->FD == FD )
  143.                 DD = AktuDD;
  144.  
  145.         u = &FD->Undos[FD->UndoTiefe];
  146.  
  147.         if((!u->typ)||(FD->UndoTiefe==FD->UndoStart-1))
  148.                 return( FALSE );
  149.  
  150.         if(FD->RedoChanges!=0)FD->RedoChanges--;
  151.         else    FD->Changes++;
  152.  
  153.         switch(u->typ)
  154.         {
  155.                 case    UT_ASCII:
  156.                         if( DD ) SetCursor(u->pos, DD);
  157.                         FD->Mem[u->pos]=u->neuwert;
  158.                         AllDisplayChar( FD, FD->Undos[ FD->UndoTiefe ].pos );
  159.                         UpdateAllStatusZeilen( FD );
  160.                         if( DD ) SetCursor(u->pos+1, DD);
  161.                         break;
  162.  
  163.                 case    UT_HEX_L:
  164.                         if( DD )
  165.                         {
  166.                                 DD->Flags |= DD_HEXEDITPOS;
  167.                                 SetCursor(u->pos, DD);
  168.                         }
  169.                         /*FD->Mem[u->pos]=u->wert;*/ /*Changed to fix case-sensitive redo bug!*/
  170.                         FD->Mem[u->pos]=u->neuwert;
  171.                         AllDisplayChar( FD, FD->Undos[ FD->UndoTiefe ].pos );
  172.                         UpdateAllStatusZeilen( FD );
  173.                         if( DD ) SetCursor(u->pos+1, DD);
  174.                         break;
  175.  
  176.                 case    UT_HEX_H:
  177.                         if( DD )
  178.                         {
  179.                                 DD->Flags &= ~DD_HEXEDITPOS;
  180.                                 SetCursor(u->pos, DD);
  181.                         }
  182.                         FD->Mem[u->pos]=u->neuwert;  /*Changed to fix case-sensitive redo-bug!!*/
  183.                         AllDisplayChar( FD, FD->Undos[ FD->UndoTiefe ].pos );
  184.                         UpdateAllStatusZeilen( FD );
  185.                         break;
  186.  
  187.                 case    UT_INSERT:
  188.                         InsertBlockForce(u->pos,u->r.mem,u->r.len, (struct DisplayData *)(((UBYTE *)FD->DisplayList.lh_Head)-sizeof(struct Node)) );
  189.                         if( DD ) SetCursor(u->pos, DD);
  190.                         break;
  191.  
  192.                 case    UT_CUT:
  193.                         if( DD ) SetCursor(u->pos, DD);
  194.                         CutBlockForce(u->pos,u->pos+u->u.len-1, (struct DisplayData *)(((UBYTE *)FD->DisplayList.lh_Head)-sizeof(struct Node)));
  195.                         break;
  196.  
  197.                 case    UT_PASTE:
  198.                         if( DD ) SetCursor(u->pos, DD);
  199.                         memcpy(FD->Mem+u->pos,u->r.mem,u->r.len);
  200.                         AllDisplay( FD, SCROLLERNEU );
  201.                         UpdateAllStatusZeilen( FD );
  202.                         break;
  203.         }
  204.  
  205.         FD->UndoTiefe++;
  206.         if(FD->UndoTiefe==UndoLevel)FD->UndoTiefe=0;
  207.  
  208.         return( TRUE );
  209. }
  210.  
  211. void FreeUndo( struct Undostruct *u, struct FileData *FD )
  212. {
  213.                 /* Eintrag löschen */
  214.  
  215.         if( u->typ & ( UT_INSERT | UT_PASTE | UT_CUT ))
  216.         {
  217.                         /* Nun Speicher freigeben */
  218.  
  219.                 FreeSpeicher( &u->r, FD );
  220.                 FreeSpeicher( &u->u, FD );
  221.         }
  222.  
  223.         u->typ = 0;
  224. }
  225.  
  226. static void AddUndo( struct FileData *FD )
  227. {
  228.         FD->UndoTiefe++;
  229.  
  230. /*      kprintf("undo steht auf: %ld Redo:%ld\n", FD->Undos[ FD->UndoTiefe ].typ, FD->RedoChanges );*/
  231.  
  232.         if(FD->UndoTiefe==UndoLevel)
  233.                 FD->UndoTiefe=0;
  234.  
  235.         if( FD->UndoTiefe == FD->UndoStart )
  236.         {
  237.                 FreeUndo( &FD->Undos[ FD->UndoStart ], FD );
  238.  
  239.                 FD->UndoStart++;
  240.                 if( FD->UndoStart == UndoLevel )
  241.                         FD->UndoStart=0;
  242.         }
  243.  
  244.         FD->Changes++;
  245.  
  246.         if( FD->RedoChanges != 0 )
  247.         {
  248.                 FD->FullChanges = FD->RedoChanges;
  249.                 FD->RedoChanges = 0;
  250.         }
  251. }
  252.  
  253. static void FreeOldUndo( struct FileData *FD )
  254. {
  255.         long k = FD->UndoTiefe;
  256.  
  257.         while( FD->Undos[ k ].typ )
  258.         {
  259. /*              kprintf("Undotyp[ %ld ] = %ld\n", k, FD->Undos[ k ].typ );*/
  260.                 FreeUndo( &FD->Undos[ k ], FD );
  261.                 k++;
  262.  
  263.                 if( k == UndoLevel )
  264.                         k = 0;
  265.         }
  266. /*      kprintf("**********************\n");*/
  267. }
  268.  
  269.  
  270. void AddUndoChar(long pos,UBYTE wert,UBYTE neuwert, struct FileData *FD )
  271. {
  272.         FreeOldUndo( FD );
  273.  
  274.         FD->Undos[FD->UndoTiefe].pos=pos;
  275.         FD->Undos[FD->UndoTiefe].wert=wert;
  276.         FD->Undos[FD->UndoTiefe].neuwert=neuwert;
  277.         FD->Undos[FD->UndoTiefe].typ=UT_ASCII;
  278.  
  279.         AddUndo( FD );
  280. }
  281.  
  282. void AddUndoCharHex(long pos,UBYTE wert,UBYTE neuwert,BOOL low, struct FileData *FD)
  283. {
  284.         FreeOldUndo( FD );
  285.  
  286.         FD->Undos[FD->UndoTiefe].pos=pos;
  287.         FD->Undos[FD->UndoTiefe].wert=wert;
  288.         FD->Undos[FD->UndoTiefe].neuwert=neuwert;
  289.         FD->Undos[FD->UndoTiefe].typ=(low==TRUE)?UT_HEX_L:UT_HEX_H;
  290.  
  291.         AddUndo( FD );
  292. }
  293.  
  294. void AddUndoInsert(long pos,struct Speicher s, struct FileData *FD)
  295. {
  296.         FreeOldUndo( FD );
  297.  
  298.         FD->Undos[FD->UndoTiefe].pos=pos;
  299.         FD->Undos[FD->UndoTiefe].typ=UT_INSERT;
  300.  
  301.         FD->Undos[FD->UndoTiefe].r = s;
  302.         FD->Undos[FD->UndoTiefe].u.mem = 0;
  303.  
  304.         AddUndo( FD );
  305.  
  306.         FD->UndoMemSize += s.len;
  307. /*kprintf("AddUndo: UndoMem:%ld\n", FD->UndoMemSize );*/
  308.         PrüfeUndomemsize( FD );
  309. }
  310.  
  311. void AddUndoCut(long pos,struct Speicher s, struct FileData *FD)
  312. {
  313.         FreeOldUndo( FD );
  314.  
  315.         FD->Undos[FD->UndoTiefe].pos=pos;
  316.         FD->Undos[FD->UndoTiefe].typ=UT_CUT;
  317.  
  318.         FD->Undos[FD->UndoTiefe].r.mem = 0;
  319.         FD->Undos[FD->UndoTiefe].u = s;
  320.  
  321.         AddUndo( FD );
  322.  
  323.         FD->UndoMemSize += s.len;
  324. /*kprintf("AddUndo: UndoMem:%ld\n", FD->UndoMemSize );*/
  325.         PrüfeUndomemsize( FD );
  326. }
  327.  
  328. void AddUndoPaste(long pos,struct Speicher ps,struct Speicher s, struct FileData *FD)
  329. {
  330.         FreeOldUndo( FD );
  331.  
  332.         FD->Undos[FD->UndoTiefe].pos = pos;
  333.         FD->Undos[FD->UndoTiefe].typ = UT_PASTE;
  334.  
  335.         FD->Undos[FD->UndoTiefe].r = s;
  336.         FD->Undos[FD->UndoTiefe].u = ps;
  337.  
  338.         AddUndo( FD );
  339.  
  340.         FD->UndoMemSize += s.len + ps.len;
  341. /*kprintf("AddUndo: UndoMem:%ld\n", FD->UndoMemSize );*/
  342.         PrüfeUndomemsize( FD );
  343. }
  344.  
  345. void PrüfeUndomemsizeRedo( struct FileData *FD )
  346. {
  347.         while( FD->UndoMemSize > maxundomemsize * 1024 )
  348.         {
  349.                 long k = FD->UndoStart;
  350.  
  351.                         /* Falls kein Eintrag mehr, abbrechen und
  352.                          * wundern! Sollte nicht passieren! */
  353.  
  354.                 if( !FD->Undos[ k ].typ )
  355.                         break;
  356.  
  357.                         /* Letzes Element suchen */
  358.  
  359.                 while( FD->Undos[ k ].typ )
  360.                 {
  361.                         k++;
  362.                         if( k == UndoLevel )
  363.                                 k = 0;
  364.                 }
  365.  
  366.                 k--;
  367.  
  368.                 if( k < 0 )
  369.                         k += UndoLevel;
  370.  
  371.                         /* k enthält die Nummer des Letzten Eintrags */
  372.  
  373.                 FreeUndo( &FD->Undos[ k ], FD );
  374.         }
  375. }
  376.  
  377. void PrüfeUndomemsize( struct FileData *FD )
  378. {
  379.         while( FD->UndoMemSize > maxundomemsize * 1024 )
  380.         {
  381.                         /* Falls kein Eintrag mehr in Liste, abbrechen */
  382.  
  383.                 if( !FD->Undos[ FD->UndoStart ].typ )
  384.                         break;
  385.  
  386.                                 /* Falls wir an aktueller Stelle ankommen, von hinten freigeben */
  387.  
  388.                 if( FD->UndoStart == FD->UndoTiefe )
  389.                 {
  390.                         PrüfeUndomemsizeRedo( FD );
  391.                         break;
  392.                 }
  393.  
  394.                         /* Undoeintrag löschen */
  395.  
  396.                 FreeUndo( &FD->Undos[ FD->UndoStart ], FD );
  397.  
  398.                 FD->UndoStart++;
  399.  
  400.                 if( FD->UndoStart == UndoLevel )
  401.                         FD->UndoStart = 0;
  402.         }
  403. }
  404.  
  405. void FreeSpeicher( struct Speicher *s, struct FileData *FD )
  406. {
  407.         if( s->len && s->mem )
  408.         {
  409.                 FreeMem( s->mem, s->len );
  410.                 FD->UndoMemSize -= s->len;
  411. /*kprintf("FreeSpeicher: UndoMem:%ld\n", FD->UndoMemSize );*/
  412.         }
  413. }
  414.  
  415. void SetMaxUndoMemSize(long new)
  416. {
  417.         if( maxundomemsize != new )
  418.         {
  419.                 struct FileData *FD;
  420.  
  421.                 maxundomemsize = new;
  422.  
  423.                 FD = (struct FileData *)FileList.lh_Head;
  424.  
  425.                 while( FD != ( struct FileData * )&FileList.lh_Tail )
  426.                 {
  427.                         PrüfeUndomemsize( FD );
  428.  
  429.                         FD = ( struct FileData *)FD->Node.ln_Succ;
  430.                 }
  431.         }
  432. }
  433.  
  434. /* SetUndoLevel
  435.  *
  436.  * Setzt die maximale Anzahl der Undoschritte in jedem File auf
  437.  * einen neuen Wert. Redo wird dabei abgeschnitten.
  438.  */
  439.  
  440. void SetUndoLevel( long neu )
  441. {
  442.         struct Undostruct *neuundos;
  443.         struct FileData *FD;
  444.  
  445.         FD = (struct FileData *)FileList.lh_Head;
  446.  
  447.         if( neu != UndoLevel )
  448.         while( FD != ( struct FileData * )&FileList.lh_Tail )
  449.         {
  450.                 if( !( neuundos = AllocMem( sizeof( struct Undostruct ) * neu, MEMF_CLEAR | MEMF_ANY )))
  451.                 {
  452.                         MyRequest( MSG_INFO_GLOBAL_CANTALLOCMEM, sizeof( struct Undostruct ) * MAX_UNDO_LEVEL );
  453.                         return;
  454.                 }
  455.  
  456.                 if( FD->UndoStart != FD->UndoTiefe )
  457.                 {
  458.                         long undolaenge;
  459.  
  460.                         if( FD->UndoStart > FD->UndoTiefe )
  461.                         {
  462.                                 undolaenge = UndoLevel + FD->UndoTiefe - FD->UndoStart;
  463.                         }
  464.                         else
  465.                         {
  466.                                 undolaenge = FD->UndoTiefe - FD->UndoStart;
  467.                         }
  468.  
  469.                         if( neu >= undolaenge )
  470.                         {
  471.                                 if( FD->UndoStart > FD->UndoTiefe )
  472.                                 {
  473.                                         memcpy( neuundos, FD->Undos + FD->UndoStart,(UndoLevel-FD->UndoStart)*sizeof(struct Undostruct));
  474.                                         memcpy( neuundos + ( UndoLevel - FD->UndoStart ),FD->Undos,FD->UndoTiefe*sizeof(struct Undostruct));
  475.                                 }
  476.                                 else
  477.                                         memcpy(neuundos,FD->Undos+FD->UndoStart,undolaenge*sizeof(struct Undostruct));
  478.  
  479.                                 FD->UndoTiefe=undolaenge;
  480.                                 FD->UndoStart=0;
  481.                         }
  482.                         else
  483.                         {
  484.                                 long k;
  485.  
  486.                                 for( k = 0; k < undolaenge - neu + 1; k++ )
  487.                                 {
  488.                                         FreeUndo( &FD->Undos[ FD->UndoStart ], FD );
  489.  
  490.                                         FD->UndoStart++;
  491.  
  492.                                         if( FD->UndoStart == UndoLevel )
  493.                                                 FD->UndoStart = 0;
  494.                                 }
  495.  
  496.                                 if( FD->UndoStart > FD->UndoTiefe)
  497.                                 {
  498.                                         memcpy(neuundos,FD->Undos+FD->UndoStart,(UndoLevel-FD->UndoStart)*sizeof(struct Undostruct));
  499.                                         memcpy(neuundos+(UndoLevel-FD->UndoStart),FD->Undos,FD->UndoTiefe*sizeof(struct Undostruct));
  500.                                 }
  501.                                 else
  502.                                         memcpy(neuundos,FD->Undos+FD->UndoStart,neu*sizeof(struct Undostruct));
  503.  
  504.                                 FD->UndoTiefe=neu-1;
  505.                                 FD->UndoStart=0;
  506.                         }
  507.                 }
  508.         
  509.                 FreeMem( FD->Undos, UndoLevel * sizeof( struct Undostruct ));
  510.  
  511.                 FD->Undos = neuundos;
  512.  
  513.                 FD = ( struct FileData *)FD->Node.ln_Succ;
  514.         }
  515.  
  516.         UndoLevel = neu;
  517. }
  518.